package com.tcp2.server;

import com.tcp2.exception.LinkException;
import com.tcp2.net.MasterLink;
import com.tcp2.net.PlatformChannel;
import com.tcp2.net.SlaveLink;
import com.yaxon.vndp.common.util.CodecUtils;
import com.yaxon.vndp.common.util.XMLConfigurationEx;
import io.netty.buffer.ByteBuf;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author: 程行荣
 * Time: 2014-05-08 10:12
 * Copyright (C) 2014 Xiamen Yaxon Networks CO.,LTD.
 */
public class MessageDispatcher {
    protected static Logger logger = LoggerFactory.getLogger(MessageDispatcher.class);

    private MasterLink masterLink;
    private SlaveLink slaveLink;
    private String configFile;
    private ApplicationContext applicationContext;
    private Map<Integer, ProtoMsgHandler> msgIdToHandlerMap = new HashMap<>();
    private int verifyCode;
    public int sn;

    public void init(ApplicationContext applicationContext) throws Exception {
        this.applicationContext = applicationContext;
        loadConfig();
    }

    public int getVerifyCode() {
        return verifyCode;
    }

    public void setVerifyCode(int verifyCode) {
        this.verifyCode = verifyCode;
    }

    private void loadConfig() throws Exception {
        try {
            Configuration conf = new XMLConfigurationEx(configFile);

            String key = null;

            for (int i=0;;i++) {
                key = "dnProtos.dnProto("+i+")";
                if (!conf.getKeys(key).hasNext()) {
                    break;
                }

                List msgIds = conf.getList(key + "[@msgIds]");
                Validate.notEmpty(msgIds, "dnProto(" + i + ")[@msgIds] 为空");

                String handlerClass = conf.getString(key + "[@handler]");
                ProtoMsgHandler handler = (ProtoMsgHandler)applicationContext.getBean(Class.forName(handlerClass));
                if (handler == null) {
                    throw new Exception("dnProto(" + i + ")[@handler] 获取实例失败: " + handlerClass);
                }
                for (Object id : msgIds) {
                    int msgId = Integer.parseInt((String) id, 16);
                    msgIdToHandlerMap.put(msgId, handler);
                }
            }
        } catch (ConfigurationException e) {
            throw new Exception("加载调度配置文件[" + configFile + "]异常: " + e.getMessage(), e);
        }
    }

    public void setConfigFile(String configFile) {
        this.configFile = configFile;
    }

    public MasterLink getMasterLink() {
        return masterLink;
    }

    public void setMasterLink(MasterLink masterLink) {
        this.masterLink = masterLink;
    }

    public SlaveLink getSlaveLink() {
        return slaveLink;
    }

    public void setSlaveLink(SlaveLink slaveLink) {
        this.slaveLink = slaveLink;
    }

    public void receiveMessage(ProtoMsg msg) {
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("-> 接收消息: msgId=0x%04X, dataLen=%d",
                    msg.msgId, msg.msgData.readableBytes()));
        }

      /*  for (int key : msgIdToHandlerMap.keySet()) {

             System.out.println("*******msgId=0x"+  CodecUtils.shortToHex((short)key));
        }
*/


        ProtoMsgHandler handler = msgIdToHandlerMap.get(msg.msgId);
        if (handler == null) {
            throw new RuntimeException("未找到消息处理器: msgId=0x" + CodecUtils.shortToHex((short)msg.msgId));
        }
        handler.handle(msg);
    }

    public void sendMessage(ProtoMsg msg, PlatformChannel platformChannel) throws LinkException {
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("<- 发送消息: msgId=0x%04X, dataLen=%d",
                    msg.msgId, msg.msgData.readableBytes()));
        }

        masterLink.sendMessage(msg,platformChannel);
    }


    /**
     * 关闭主从链路
     */
    public void closeLink() {

    }

    /**
     * 开启主从链路
     */
    public void openLink() {

    }
    /**
     * 保存从链路数据交互记录
     * @param msgId
     * @param msgTxt
     * @param data
     * @param type
     */
    public void saveSlaveLinkExcLog(String msgId, String msgTxt, ByteBuf data, Byte type){

        //转换成二进制字符串
        String dataStr="";
        int size=data.readableBytes();
        if(size>0) {
            byte[] bytes = new byte[size];
            data.readBytes(bytes);
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                dataStr += hex.toUpperCase();
            }
        }

    }
}

